package com.shanzmoo.admin.aop;

import cn.hutool.core.exceptions.ExceptionUtil;
import com.alibaba.fastjson.JSON;
import com.shanzmoo.core.cache.CurrentUserCache;
import com.shanzmoo.db.sys.entity.LogEntity;
import com.shanzmoo.db.sys.service.ILogService;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;

/**
 * 日志拦截器
 *
 * @author： Gzhao 2021/1/16
 */
@Slf4j
@Aspect
@Component
public class WebLogAspect {

    private static final List<String> NOT_SAVE_URL = Arrays.asList(
            "/sys/base/addressTree",
            "/open/callback/alipay",
            "/open/callback/wxpay",
            "/open/oss/policy",
            "/open/oss/callback",
            "/api/order/obtainImportSkuList",
            "/third/platform/order/import"
    );

    @Autowired
    private ILogService logService;

    @Pointcut("execution(public * com.shanzmoo.admin.web.*.*(..)) " +
            "&& !execution(public * com.shanzmoo.admin.web.trade.OpenCallbackController.*(..))")
    public void webLog() {
    }


    @Around("webLog()")
    public Object saveSysLog(ProceedingJoinPoint joinPoint) throws Throwable {
        LogEntity logEntity = new LogEntity();

        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        //获取请求方法信息
        String className = joinPoint.getTarget().getClass().getName();
        String methodName = method.getName();
        //请求的参数
        Object[] args = joinPoint.getArgs();

        HttpServletRequest request = null;
        Object result = null;
        boolean success = true;
        Throwable te = null;
        try {
            request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            logEntity.setStartTime(LocalDateTime.now());

            result = joinPoint.proceed(args);

            logEntity.setOutParam(JSON.toJSONString(result));

        } catch (Throwable throwable) {
            te = throwable;
            success = false;

            logEntity.setOutParam("throwable : " + ExceptionUtil.getRootCauseMessage(throwable));

            // todo 发送异常邮件

        } finally {
            try {
                if (!NOT_SAVE_URL.contains(request.getRequestURI())) {
                    logEntity.setResult(success);
                    logEntity.setEndTime(LocalDateTime.now());

                    logEntity.setUserId(CurrentUserCache.getUserId());
                    logEntity.setUserIp(request.getRemoteAddr());
                    logEntity.setUri(request.getRequestURI());
                    logEntity.setCalssName(className);
                    logEntity.setMethodName(methodName);

                    log.info("logInfo:{}", JSON.toJSONString(logEntity));
                    log.info("args", args);
                    logEntity.setInParam(JSON.toJSONString(args));

                    logService.save(logEntity);
                }
            } catch (Exception e){
                log.error("日志保存异常", e);
            }

            if (success) {
                return result;
            } else {
                if (null == te) {
                    te = new Exception("内部系统异常");
                }
                throw te;
            }
        }
    }
}
